﻿@{
    ViewBag.Title = "FileUploadForm";
}
<link href="~/Scripts/jquery-plugins/webuploader-0.1.5/webuploader.css" rel="stylesheet" />
<link href="~/Scripts/jquery-plugins/webuploader-0.1.5/my.css" rel="stylesheet" />
<script src="~/Scripts/jquery-plugins/webuploader-0.1.5/webuploader.js"></script>
<div id="uploader" class="wu-example">
    <!--用来存放文件信息-->
    <div id="thelist" class="uploader-list"></div>
    <div class="btns">
        <div id="picker">选择文件</div>
        <button id="ctlBtn" class="btn btn-default">开始上传</button><br />
        <button id="btnStop" class="btn btn-default">暂停上传</button><br />
        <button id="btnContinue" class="btn btn-default">继续上传</button><br />
        <button id="btnClear" class="btn btn-default">清除已有md5</button><br />
        <div id="resultInfo"></div>
    </div>
</div>
<script>
    //自定义字典对象
    function Dictionary() {
        this.data = new Array();

        this.put = function (key, value) {
            this.data[key] = value;
        };

        this.get = function (key) {
            return this.data[key];
        };

        this.remove = function (key) {
            this.data[key] = null;
        };

        this.isEmpty = function () {
            return this.data.length == 0;
        };

        this.size = function () {
            return this.data.length;
        };
    }

    $(function () {
        var $list = $("#thelist");
        var hash = []; var nexts = new Dictionary();

        //整个文件生成md5
        //WebUploader.Uploader.register({
        //    'before-send-file': 'preupload'
        //}, {
        //    preupload: function (file) {
        //        var me = this,
        //            owner = this.owner,
        //            server = me.options.server,
        //            deferred = WebUploader.Deferred();

        //        nexts.put(file.id, 0);
        //        console.log(file.name + "文件执行before-send-file事件，文件总大小：" + file.size);
        //        deferred.resolve();
        //        //console.log(file.name + "的before-send-file事件");
        //        //owner.md5File(file.source)
        //        //    // 如果读取出错了，则通过reject告诉webuploader文件上传出错。
        //        //    .fail(function () {
        //        //        deferred.reject();
        //        //    })
        //        //    // md5值计算完成
        //        //    .then(function (md5) {
        //        //        console.log(file.name + "的md5值：" + md5);
        //        //        $.ajax(server, {
        //        //            dataType: 'json',
        //        //            data: {
        //        //                md5: md5
        //        //            },
        //        //            success: function (response) {
        //        //                //如果验证已经上传过
        //        //                if (response.exist) {
        //        //                    owner.skipFile(file);
        //        //                    console.log(file.name + '文件重复，已跳过。');
        //        //                }
        //        //                deferred.resolve();
        //        //            }
        //        //        });
        //        //    });

        //        return deferred.promise();
        //    }
        //});

        //分片生成md5
        WebUploader.Uploader.register({
            "before-send": "checkChunk"
        }, {
            checkChunk: function (block) {
                var me = this, owner = this.owner, deferred = $.Deferred();
                //block有属性：chunk当前分片索引 chunks总分片数 start分片起始点 end分片结尾点 total文件总点
                console.log(block.file.name + "文件的第" + block.chunk + "个分片开始执行的before-send事件");
                console.log("这个分片的属性：");
                console.log("分片号：" + block.chunk);
                console.log("分片总数：" + block.chunks);
                console.log("分片起始点：" + block.start);
                console.log("分片结尾点：" + block.end);
                console.log("分片所属文件总长度1：" + block.total);
                var next = nexts.get(block.file.id);
                if (!next) { next = 0; }
                if (block.start < next) {
                    //console.log("第" + block.chunk + "个分片的起始byte是" + block.start + "，服务器返回的next是：" + next + "，直接跳过。");
                    //deferred.reject();
                    deferred.resolve();
                }
                else {
                    owner.md5File(block.blob)
                        .fail(function () {
                            // 读取md5出错的话，分片不能跳过。
                            deferred.resolve();
                        })
                        .then(function (md5) {
                            //console.log("第" + block.chunk + "个分片的md5值：" + md5);

                            if (hash[md5]) {
                                console.log("第" + block.chunk + "个分片重复，已拒绝。");
                                deferred.reject();
                            } else {
                                hash.push(md5);
                                deferred.resolve();
                            }
                        });
                }
                return deferred.promise();
            }
        });

        WebUploader.Uploader.register({ "after-send-file": "dealTemp" }, {
            dealTemp: function (file) {
                $.post("/Attachment/DealFileTemp", { fileName: file.name, md5: "" }, function (result) {
                    $.messager.alert(result.success);
                });
            }
        });



        var uploader = WebUploader.create({

            // swf文件路径
            swf: "/Scripts/jquery-plugins/webuploader-0.1.5/Uploader.swf",

            // 文件接收服务端。
            server: "/Attachment/UploadFile",

            // 选择文件的按钮。
            // 内部根据当前运行是创建，可能是input元素，也可能是flash.
            pick: { id: "#picker", multiple: true },

            // 是否自动上传。
            auto: false,

            // 是否去重。若去重，会根据文件名字、文件大小和最后修改时间来生成hash Key
            duplicate: true,

            // 是否要分片处理大文件上传。
            chunked: true,

            // 每块分片大小，这是5M不到
            chunkSize: 5 * 1000 * 1000,

            // 上传并发数。允许同时最大上传进程数
            threads: 1,

            // 是否允许在文件传输时提前把下一个文件准备好。 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。 如果能提前在当前文件传输期处理，可以节省总体耗时。
            prepareNextFile: true,

            //如果此选项为false, 则图片在上传前不进行压缩。这个属性需要注意，当开启自动压缩图片时，那些容量比较大的图标，被压缩后，分片上传时的分片数量会比“原本应该的分片数量”要少。比如上传20M的图片，分片5M的话，要4个分片。而压缩之后，可能就只需要1个分片就完成上传了。
            compress: false
        });



        // 当文件被加入队列之前触发，此事件的handler返回值为false，则此文件不会被添加进入队列。
        uploader.on("beforeFileQueued", function (file) {
            //console.log("执行beforeFileQueued事件：当文件被加入队列之前触发");
            return true;
        });

        // 当有文件被添加进队列的时候触发
        // file属性有 id name(全名) ext(扩展名) loaded(值为0，应该表示是否加载) size statusText(空) type("image/gif")
        uploader.on("fileQueued", function (file) {
            //console.log("执行fileQueued事件：当有文件被添加进队列的时候触发");
            $list.append("<div id=\"" + file.id + "\" class=\"queue-item\">" +
                "<h4>" + file.name + " (" + file.size + ")</h4>" +
                "<a class=\"cancel\" href=\"javascript:void(0);\"></a>" +
                "<p class=\"state\">等待上传...</p>" +
            "</div>");
            $("div#" + file.id + " a.cancel").bind("click", function () {
                uploader.removeFile(file, true);
            });
        });

        // 当一批文件添加进队列以后触发。对每个file执行fileQueued事件之后，再触发本事件。
        uploader.on("filesQueued", function (files) {
            //console.log("执行filesQueued事件：当一批文件添加进队列以后触发");
        });

        // 当文件被移除队列后触发。
        uploader.on("fileDequeued", function (file) {
            //console.log("执行fileDequeued事件：当文件被移除队列后触发");
            $("div#" + file.id + "").fadeOut();
            setTimeout(function () {
                $("div#" + file.id + "").remove();
            }, 1000);
        });

        // 当开始上传流程时触发。
        uploader.on("startUpload", function () {
            hash = [];
            //console.log("执行startUpload事件：当开始上传流程时触发");
        });

        // 当开始上传流程暂停时触发。
        uploader.on("stopUpload", function () {
            //console.log("执行stopUpload事件：当开始上传流程暂停时触发");
        });

        // 当所有文件上传结束时触发。
        uploader.on("uploadFinished", function () {
            //console.log("执行uploadFinished事件：当所有文件上传结束时触发");
        });

        // 某个文件开始上传前触发，一个文件只会触发一次。
        uploader.on("uploadStart", function (file) {
            //console.log("执行uploadStart事件：某个文件开始上传前触发，一个文件只会触发一次。本次文件md5：" + file.md5);
        });

        // 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。
        uploader.on("uploadBeforeSend", function (object, data, header) {
            //block有属性：chunk当前分片索引 chunks总分片数 start分片起始点 end分片结尾点 total文件总点
            //console.log("第" + object.chunk + "个分片执行uploadBeforeSend事件：当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。本次分片md5：" + object.md5);
            $.extend(header, { "Content-Range": "bytes " + object.start + "-" + object.end + "/" + object.total, "Content-Disposition": "attachment;filename=\"" + escape(object.file.name) + "\"" });
        });

        // 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为false, 则此文件将派送server类型的uploadError事件。
        uploader.on("uploadAccept", function (object, ret) {
            console.log(object.file.name + "文件的第" + object.chunk + "个分片执行uploadAccept事件，返回的next是：" + ret.next);
            nexts.put(object.file.id, ret.next);
        });

        // 上传过程中触发，携带上传进度。
        uploader.on("uploadProgress", function (file, percentage) {
            //console.log("执行uploadProgress事件：上传过程中触发，携带上传进度。当前进度：" + percentage);
            var $li = $('#' + file.id),
                $percent = $li.find('.progress .bar');

            // 避免重复创建
            if (!$percent.length) {
                $percent = $('<span class="progress">' +
                    '<span  class="percentage"><span class="text"></span>' +
                  '<span class="bar" role="progressbar" style="width: 0%">' +
                  '</span></span>' +
                '</span>').appendTo($li).find('.bar');
            }

            $li.find('p.state').text('上传中');
            $li.find("span.text").text(Math.round(percentage * 100) + '%');
            $percent.css('width', percentage * 100 + '%');
        });

        // 当文件上传成功时触发。
        uploader.on("uploadSuccess", function (file, response) {
            //console.log("执行uploadSuccess事件：当文件上传成功时触发");
            var $li = $('#' + file.id);
            $li.find("a.cancel").hide();
            $li.find("p.state").text("已上传");
        });

        // 当文件上传出错时触发。
        uploader.on("uploadError", function (file, reason) {
            //console.log("执行uploadError事件：当文件上传出错时触发");
            $('#' + file.id).find("p.state").text("上传出错");
            $("#resultInfo").append("文件：" + file.name + "，上传出错原因：" + reason).append("<br />");
        });

        // 不管成功或者失败，文件上传完成时触发。
        uploader.on('uploadComplete', function (file) {
            //console.log("执行uploadComplete事件：不管成功或者失败，文件上传完成时触发");
            $('#' + file.id).find('.progress').fadeOut();
        });

        $("#ctlBtn").click(function () {
            uploader.upload();
        });

        $("#btnStop").click(function () {
            uploader.stop(true);  //第一个参数为是否中断上传当前正在上传的文件。如果第一个参数是文件，则只暂停指定文件。
        });

        $("#btnContinue").click(function () {
            uploader.upload();//此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。参数可以是文件
        });

        $("#btnClear").click(function () {
            $.post("/Attachment/ClearStaticMd5", function (result) { if (result.success) { $.messager.alert("清除成功！"); } });
        });
    });
</script>

